package com.mdc.mansion.common.util.builder;

import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.StandardToStringStyle;

/**
 * @author xuyang
 * 
 */
public class CustomToStringStyle extends StandardToStringStyle {

	private String mapStart = "[";

	private String mapEnd = "]";

	private String mapSeparator = ", ";

	private String mapKeyValueSeparator = "=";

	private boolean mapContentDetail = true;

	private String enumerationStart = "[";

	private String enumerationEnd = "]";

	private String enumerationSeparator = ", ";

	private boolean enumerationContentDetail = true;

	private boolean enumContentDetail = false;

	private CustomToStringBuilder customToStringBuilder;

	/**
	 * 
	 */
	private static final long serialVersionUID = 6560842766217639161L;

	public CustomToStringStyle() {
		super();
		super.setContentStart("{");
		super.setContentEnd("}");
		super.setFieldSeparator("; ");
		// super.setFieldSeparatorAtStart(true);
		// super.setFieldSeparatorAtEnd(true);
		super.setArrayStart("[");
		super.setArrayEnd("]");
		super.setArraySeparator(", ");
	}

	@Override
	protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
		if (value instanceof Number || value instanceof Boolean || value instanceof Character
				|| value instanceof CharSequence) {
			this.append(buffer, value);
		} else if (value instanceof Date) {
			this.appendDetail(buffer, fieldName, (Date) value);
		} else if (value instanceof Enumeration<?>) {
			this.appendDetail(buffer, fieldName, (Enumeration<?>) value);
		} else if (value instanceof Enum<?>) {
			this.appendDetail(buffer, fieldName, (Enum<?>) value);
		} else {
			ReflectionToStringBuilder builder = new ReflectionToStringBuilder(value, this, buffer,
					customToStringBuilder.getUpToClass(), customToStringBuilder.isAppendTransients(),
					customToStringBuilder.isAppendStatics());
			builder.setExcludeFieldNames(customToStringBuilder.getExcludeFieldNames());
			builder.toString();
		}
	}

	protected void reflectionAppendArrayDetail(StringBuffer buffer, String fieldName, Object array) {
		super.reflectionAppendArrayDetail(buffer, fieldName, array);
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void appendDetail(StringBuffer buffer, String fieldName, Collection coll) {
		this.reflectionAppendArrayDetail(buffer, fieldName, coll.toArray());
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void appendDetail(StringBuffer buffer, String fieldName, Map map) {
		Set<Map.Entry<?, ?>> set = map.entrySet();
		buffer.append(mapStart);
		int i = 0;
		for (Map.Entry<?, ?> entry : set) {
			Object key = entry.getKey();
			Object value = entry.getValue();
			if (i > 0) {
				buffer.append(mapSeparator);
			}
			if (key == null) {
				appendNullText(buffer, fieldName);
			} else {
				appendInternal(buffer, fieldName, key, mapContentDetail);
			}
			buffer.append(mapKeyValueSeparator);
			if (value == null) {
				appendNullText(buffer, fieldName);
			} else {
				appendInternal(buffer, fieldName, value, mapContentDetail);
			}
			i++;
		}
		buffer.append(mapEnd);
	}

	protected void append(StringBuffer buffer, Object value) {
		buffer.append(value);
	}

	protected void appendDetail(StringBuffer buffer, String fieldName, Date date) {
		super.appendContentStart(buffer);
		buffer.append(date);
		super.appendContentEnd(buffer);
	}

	protected void appendDetail(StringBuffer buffer, String fieldName, Enumeration<?> enumeration) {
		buffer.append(enumerationStart);
		int i = 0;
		while (enumeration.hasMoreElements()) {
			Object item = enumeration.nextElement();
			if (i > 0) {
				buffer.append(enumerationSeparator);
			}
			if (item == null) {
				appendNullText(buffer, fieldName);
			} else {
				appendInternal(buffer, fieldName, item, enumerationContentDetail);
			}
			i++;
		}
		buffer.append(enumerationEnd);
	}

	protected void appendDetail(StringBuffer buffer, String fieldName, Enum<?> e) {
		if (enumContentDetail) {
			new ReflectionToStringBuilder(e, this, buffer).toString();
		} else {
			buffer.append(e);
		}
	}

	/**
	 * @return the mapStart
	 */
	public String getMapStart() {
		return mapStart;
	}

	/**
	 * @param mapStart
	 *            the mapStart to set
	 */
	public void setMapStart(String mapStart) {
		this.mapStart = mapStart;
	}

	/**
	 * @return the mapEnd
	 */
	public String getMapEnd() {
		return mapEnd;
	}

	/**
	 * @param mapEnd
	 *            the mapEnd to set
	 */
	public void setMapEnd(String mapEnd) {
		this.mapEnd = mapEnd;
	}

	/**
	 * @return the mapSeparator
	 */
	public String getMapSeparator() {
		return mapSeparator;
	}

	/**
	 * @param mapSeparator
	 *            the mapSeparator to set
	 */
	public void setMapSeparator(String mapSeparator) {
		this.mapSeparator = mapSeparator;
	}

	/**
	 * @return the mapKeyValueSeparator
	 */
	public String getMapKeyValueSeparator() {
		return mapKeyValueSeparator;
	}

	/**
	 * @param mapKeyValueSeparator
	 *            the mapKeyValueSeparator to set
	 */
	public void setMapKeyValueSeparator(String mapKeyValueSeparator) {
		this.mapKeyValueSeparator = mapKeyValueSeparator;
	}

	/**
	 * @return the mapContentDetail
	 */
	public boolean isMapContentDetail() {
		return mapContentDetail;
	}

	/**
	 * @param mapContentDetail
	 *            the mapContentDetail to set
	 */
	public void setMapContentDetail(boolean mapContentDetail) {
		this.mapContentDetail = mapContentDetail;
	}

	/**
	 * @return the enumerationStart
	 */
	public String getEnumerationStart() {
		return enumerationStart;
	}

	/**
	 * @param enumerationStart
	 *            the enumerationStart to set
	 */
	public void setEnumerationStart(String enumerationStart) {
		this.enumerationStart = enumerationStart;
	}

	/**
	 * @return the enumerationEnd
	 */
	public String getEnumerationEnd() {
		return enumerationEnd;
	}

	/**
	 * @param enumerationEnd
	 *            the enumerationEnd to set
	 */
	public void setEnumerationEnd(String enumerationEnd) {
		this.enumerationEnd = enumerationEnd;
	}

	/**
	 * @return the enumerationSeparator
	 */
	public String getEnumerationSeparator() {
		return enumerationSeparator;
	}

	/**
	 * @param enumerationSeparator
	 *            the enumerationSeparator to set
	 */
	public void setEnumerationSeparator(String enumerationSeparator) {
		this.enumerationSeparator = enumerationSeparator;
	}

	/**
	 * @return the enumerationContentDetail
	 */
	public boolean isEnumerationContentDetail() {
		return enumerationContentDetail;
	}

	/**
	 * @param enumerationContentDetail
	 *            the enumerationContentDetail to set
	 */
	public void setEnumerationContentDetail(boolean enumerationContentDetail) {
		this.enumerationContentDetail = enumerationContentDetail;
	}

	/**
	 * @return the enumContentDetail
	 */
	public boolean isEnumContentDetail() {
		return enumContentDetail;
	}

	/**
	 * @param enumContentDetail
	 *            the enumContentDetail to set
	 */
	public void setEnumContentDetail(boolean enumContentDetail) {
		this.enumContentDetail = enumContentDetail;
	}

	/**
	 * @param customToStringBuilder
	 *            the customToStringBuilder to set
	 */
	protected void setCustomToStringBuilder(CustomToStringBuilder customToStringBuilder) {
		this.customToStringBuilder = customToStringBuilder;
	}

}
